#include "include.h"
#include "api.h"

void uart_1_isr_init(void(*uart1_isr_func));

#if IODM_TEST_MODE

typedef struct {
    u8 header;
    u8 cmd;
    u8 len;
    u8 data[];
} uart_cmd_t;

iodm_test_mode iodm;
u8 iodm_uart1_buffer[40];
u8 fcc_param[10];
u32 bt_get_xosc_cap(void);
void bt_set_xosc_cap(u32 cap);
u8 param_bt_xosc_read(void);
void uart_1_isr_init(void(*uart1_isr_func));
void uart1_putchar(u8 ch);

u8 crc8_maxim(u8 *buf, u8 length)
{
    u8 i;
    u8 crc = 0;
    my_printf("crc8_maxim:\n");
    print_r(buf, length);
    while (length--) {
        crc ^= *buf++;
        for (i = 0; i < 8; i++) {
            if (crc & 1) {
                crc = (crc >> 1) ^ 0x8c;
            } else {
                crc >>= 1;
            }
        }
    }
    return crc;
}

//void uart1_putchar(char ch)
//{
//    UART1DATA = ch;
//    while (!(UART1CON & BIT(8)));
//
//}

void iodm_send_data(u8 *buf, u16 len)
{
    my_printf("iodm_send_data: ");
    print_r(buf, len);
    for (u8 i = 0; i < len; i++) {
        uart1_putchar(buf[i]);
    }
}


/**
* @brief       Data mgr response cmd
* @param[in]   p_cmd_rsp command response buffer
* @param[in]   len       buffer len
* @param[in]   result    command response data
* @retval      0         Success
* @retval      other     Error
*/
u8 uart_cmd_rsp(uart_cmd_t *p_cmd_rsp, u8 len, u8 result)
{
    p_cmd_rsp->header = UART_CMD_RSP_HEAD;
    /* p_cmd_rep->cmd = ack request->cmd */
    p_cmd_rsp->cmd   |= 0x80;
    p_cmd_rsp->len    = len;

    u8 result_index = AM_OFFSET(uart_cmd_t, data) + p_cmd_rsp->len;
    u8 *ptr = &((u8 *)p_cmd_rsp)[result_index];

    if (result_index >= (sizeof(iodm_uart1_buffer) - 4)) {
        my_printf("uart_cmd_rsp len err!!!!\n");
        return 1;
    }
    ptr[0] = result;
    ptr[1] = crc8_maxim((uint8_t *)p_cmd_rsp, result_index + 1);
    ptr[2] = '\\';
    ptr[3] = 'n';
    iodm_send_data((u8 *)p_cmd_rsp, result_index + 4);
    return 0;
}


void iodm_reveice_data_deal(void)
{
    my_printf("receice_data:\n");

    uart_cmd_t *p_uart_cmd;
    uart_cmd_t *p_cmd_rsp = (uart_cmd_t *)&iodm_uart1_buffer[0];
    u8 cmd_rsp_param_len = 0;
    u8 result = IODM_RESULT_OK;
    print_r(iodm_uart1_buffer, iodm.uart1_reveice_cnt);
    u8 start_idx, result_ok = 0;           // 理想情况下起始信号存放在第一个字节, 防止前面有异常数据
    for (start_idx = 0; start_idx < 15; start_idx++) {
        if (iodm_uart1_buffer[start_idx] == UART_CMD_HEAD) {
            result_ok = 1;
            break;
        }
    }
    p_uart_cmd = (uart_cmd_t *)&iodm_uart1_buffer[start_idx];
    if (result_ok) {
        if ((p_uart_cmd->len + start_idx) < (sizeof(iodm_uart1_buffer) - 6)) {
            u8 check_crc = crc8_maxim(&p_uart_cmd->header, AM_OFFSET(uart_cmd_t, data) + p_uart_cmd->len);
            my_printf("iodm cmd receive crc: %x, check_crc: %x\n", p_uart_cmd->data[p_uart_cmd->len], check_crc);
            if (check_crc == p_uart_cmd->data[p_uart_cmd->len]) {
                // 校验成功
                my_printf("iodm cmd check success\n");
            } else {
                // 校验失败
                my_printf("iodm cmd check fail\n");
                result = IODM_RESULT_CHECK_FAIL;
            }
        } else {
            // 校验失败
            my_printf("iodm cmd check fail\n");
            result = IODM_RESULT_CHECK_FAIL;
        }
    }
    if (result == IODM_RESULT_CHECK_FAIL) {
        uart_cmd_rsp(p_cmd_rsp, cmd_rsp_param_len, result);
        iodm.uart1_reveice_cnt = 0;
        return;
    }

    switch (p_uart_cmd->cmd) {
        case IODM_DEV_RST:
            my_printf("IODM_DEV_RST\n");
            cm_write8(PARAM_RST_FLAG, RST_FLAG_MAGIC_VALUE);
            cm_sync();
            result = IODM_RESULT_OK;
            uart_cmd_rsp(p_cmd_rsp, cmd_rsp_param_len, result);
            // WDT_RST();
            break;

        case IODM_SET_BT_ADDR:
            my_printf("iodm IODM_SET_BT_ADDR\n");
            bt_save_qr_addr(p_uart_cmd->data);
            result = IODM_RESULT_OK;
            break;

        case IODM_SET_BT_NAME:
            my_printf("iodm IODM_SET_BT_NAME\n");
            bt_save_new_name((char *)p_uart_cmd->data, p_uart_cmd->len);
            result = IODM_RESULT_OK;
            break;

        case IODM_CBT_TEST:
            my_printf("iodm IODM_CBT_TEST\n");
            result = IODM_RESULT_OK;
            if (func_cb.sta != FUNC_BT_CBT) {
                func_cb.sta = FUNC_BT_CBT;
            }
            break;

        case IODM_FCC_TEST:
            my_printf("iodm IODM_FCC_TEST\n");
            bt_cfg.fcc_test_mode = 1;
            result = IODM_RESULT_OK;
            if (func_cb.sta != FUNC_BT_FCC) {
                func_cb.sta = FUNC_BT_FCC;
            }
            break;

        case IODM_FCC_SET_PARAM:
            if (func_cb.sta == FUNC_BT_FCC) {
                //fcc_param = p_uart_cmd->data;
                memcpy(fcc_param, p_uart_cmd->data, sizeof(fcc_param));
                //            my_printf("fcc_param:");
                //            print_r(fcc_param, 0x0a);
                bt_fcc_test_start();
                result = IODM_RESULT_OK;
            } else {
                result = IODM_RESULT_STAT_ERR;
            }
            break;
        case IODM_SET_XOSC_CAP:
        {
            u8 xtal = p_uart_cmd->data[0];
            if (xtal < 63) {
                bt_set_xosc_cap(xtal);   //设置 频偏参数
                result = IODM_RESULT_OK;
            } else {
                result = IODM_RESULT_PARAM_INVALID;
            }
            break;
        }

        case IODM_GET_VER_INFO:
            cmd_rsp_param_len = 4;
            memcpy(&p_cmd_rsp->data[0], IODM_HARDWARE_VER, 2);
            memcpy(&p_cmd_rsp->data[2], IODM_SOFTWARE_VER, 2);
            result = IODM_RESULT_OK;
            my_printf("iodm IODM_GET_VER_INFO:");
            print_r(p_cmd_rsp->data, 4);
            break;

        case IODM_GET_BT_ADDR:
            cmd_rsp_param_len = sizeof(xcfg_cb.bt_addr);
            if (bt_get_qr_addr(p_cmd_rsp->data)) {
                result = IODM_RESULT_OK;
                my_printf("iodm Get bt addr ok\n");
            } else {
                bool bt_get_master_addr(u8 * addr);
                if (!bt_get_master_addr(p_cmd_rsp->data)) {

                    memcpy(p_cmd_rsp->data, xcfg_cb.bt_addr, 6);
                }
                my_printf("iodm Get bt addr raw\n");
                result = IODM_RESULT_NO_PREPARE;
            }
            break;

        case IODM_GET_BT_NAME:
            if (bt_get_new_name((char *)p_cmd_rsp->data)) {
                cmd_rsp_param_len = strlen((char *)p_cmd_rsp->data) + 1;
                my_printf("iodm Get bt name %d\n", cmd_rsp_param_len);
            } else {
                cmd_rsp_param_len = strlen(xcfg_cb.bt_name) + 1;
                memcpy(p_cmd_rsp->data, xcfg_cb.bt_name, p_cmd_rsp->len);
                my_printf("iodm Get bt name raw\n");
            }
            result = IODM_RESULT_OK;
            break;

        case IODM_CBT_TEST_EXIT:
            my_printf("iodm cbt exit\n");
            result = IODM_RESULT_OK;
            if (func_cb.sta != FUNC_BT) {
                func_cb.sta = FUNC_BT;
                break;
            }
            break;

        case IODM_FCC_TEST_EXIT:
            my_printf("iodm fcc exit\n");
            bt_cfg.fcc_test_mode = 0;
            result = IODM_RESULT_OK;
            if (func_cb.sta != FUNC_BT) {
                func_cb.sta = FUNC_BT;
                break;
            }
            break;

        case IODM_GET_XOSC_CAP:
            my_printf("iodm get xosc cap\n");
            cmd_rsp_param_len = 1;
            u8 cap_param = param_bt_xosc_read_api();
            if (cap_param == 0xff) {
                p_cmd_rsp->data[0] = xcfg_cb.osci_cap;
            } else {
                cap_param &= ~0x80;
                p_cmd_rsp->data[0] = (cap_param & 0x7) << 3;
                p_cmd_rsp->data[0] |= (cap_param >> 3) & 0x07;
            }
            result = IODM_RESULT_OK;
            break;

        case IODM_CLEAR_ADD:
            cm_write8(PARAM_MASTER_ADDR_VALID, 0);      //清除双发地址
            cm_sync();
            result = IODM_RESULT_OK;
            break;

        default:
            result = IODM_RESULT_CMD_UNKNOW;
    }
    uart_cmd_rsp(p_cmd_rsp, cmd_rsp_param_len, result);
    iodm.uart1_reveice_cnt = 0;
    //    my_printf("iodm_reveice_data_deal end\n");
}

u8 *get_fcc_param(void)
{
    my_printf("%s:", __func__);
    print_r(fcc_param, 0x0a);
    return fcc_param;
}

AT(.com_text.uart)
void iodm_test_mode_uart1_isr(void)
{
    if (UART1CON & BIT(9)) {
        UART1CPND = BIT(9);
        u8 ch = UART1DATA;
        iodm_uart1_buffer[iodm.uart1_reveice_cnt] = ch;
        if (ch == 0x6e && iodm_uart1_buffer[iodm.uart1_reveice_cnt - 1] == 0x5c) { //接收到 "\n" 表示结束 发消息处理数据
            // msg_enqueue(EVT_IODM_TEST_MODE);
        }
        iodm.uart1_reveice_cnt++;
        if (iodm.uart1_reveice_cnt >= sizeof(iodm_uart1_buffer)) {
            iodm.uart1_reveice_cnt = 0;
        }
    }
}


void uart1_init(u32 baudrate)
{
    u32 baud = 0;
    baud = (26000000 / 2 + baudrate / 2) / baudrate - 1; //时钟源x26m_div2 //baud/2 四舍五入
    // register_isr(IRQ_UART_VECTOR, iodm_test_mode_uart1_isr);
    UART1CON = 0;
    GPIOAPU  |= (BIT(3) | BIT(4));     //RX->PA3   TX ->PA4
    GPIOAFEN |= (BIT(3) | BIT(4));      //Port Function EN
    GPIOADIR &= ~BIT(4);
    GPIOADIR |= BIT(3);
    GPIOADE  |= (BIT(3) | BIT(4));
    FUNCMCON0 |= (0xf << 28) | (0xf << 24);  //clear map
    FUNCMCON0 |= (0x2 << 28) | (0x2 << 24);      // MAP G2

    UART1BAUD = (baud << 16) | baud;  //baud rate = sys_clk/(UART1BAUD + 1)   16~31接收波特率  0~15 发送波特率
    //UART1CON &= ~(BIT(6) | BIT(5) | BIT(4) | BIT(1)); //BIT(6) 0 RX/TX separate，1 RX/TX one line；BIT(5) 0使用system clock，1uart_inc；BIT(4)0 1个停止位，1 2个停止位;BIT(1) 0 8bit模式，1 9Bit模式
    UART1CON |= BIT(7) | BIT(5) | BIT(2);
    UART1CON |=  BIT(0); // BIT(7)RX使能，BIT(3)使能TX中断，BIT(2)使能RX中断，BIT(0)使能串口
    CLKCON1 |= BIT(14);
    uart_1_isr_init(iodm_test_mode_uart1_isr);
}

void iodm_test_mode_uart1_init(void)
{
    memset(&iodm, 0x00, sizeof(iodm));
    memset(iodm_uart1_buffer, 0x00, sizeof(iodm_uart1_buffer));
    uart1_init(9600);
    my_printf("uart1_init %x\n", UART1CON);
    for (u8 i = 0; i < 5; i++) {
        uart1_putchar(0x55);
    }
}

/* uart io data mgr */

#define FRAME_HEADER                0xAC69   // 帧头
#define MIN_FRAME_SIZE              10       // 最小帧大小 (帧头2 + 长度2 + ID1 + CMD1 + 校验和2)
#define FRAME_CMD_BUFFER_SIZE       1024
#define PROTOCOL_FRAME_SIZE         (MIN_FRAME_SIZE + FRAME_CMD_BUFFER_SIZE)
#define MAX_SPP_TX_DATA_SIZE        240
#define SPP_TRANSFER_RETRY_CNT      3

typedef struct
{
    u16 frame_head;
    u16 frame_len;
    u8  frame_id;
    u8  cmd_id;
    u16 cmd_len;
    u8  cmd_value[FRAME_CMD_BUFFER_SIZE];
    u16 checksum;
} protocol_frame_t;

// 错误码定义
typedef enum {
    ERR_NONE = 0,
    ERR_FRAME_HEAD,         // 帧头错误
    ERR_FRAME_LEN,          // 帧长度错误
    ERR_BUFFER_OVERFLOW,    // 缓冲区溢出
    ERR_CHECKSUM,           // 校验和错误
    ERR_CMD_LEN,            // 命令长度错误
} protocol_error_t;

// 协议帧状态
typedef enum {
    FRAME_FIND_HEAD,    // 查找帧头
    FRAME_GET_LEN,      // 获取长度
    FRAME_GET_DATA,     // 获取数据
    FRAME_CHECK         // 校验
} frame_state_t;

// 解析结果
typedef enum {
    PARSE_OK,           // 解析成功
    PARSE_NEED_DATA,    // 需要更多数据
    PARSE_ERROR         // 解析错误
} parse_result_t;


typedef struct {
    u16 cnt;
    u8 buffer[PROTOCOL_FRAME_SIZE];
    protocol_frame_t frame;         // 当前帧
    frame_state_t parse_state;      // 解析状态
    protocol_error_t error_type;    // 帧错误类型
} uart_datamgr_t;


static uart_datamgr_t g_uart_datamgr = {0};
static char g_log_buf[256] = {0};
static u8 g_tx_buf[PROTOCOL_FRAME_SIZE] = {0};

isr_t register_isr(int vector, isr_t isr);
void my_printf_init(void (*putchar)(char));
bool bt_get_master_addr(u8 *addr);
void uart_putchar(char ch);


static void uart0_putchar(u8 data)
{
    while (!(UART0CON & BIT(8)));
    UART0DATA = data;
}

static void iodm_uart0_data_send(u8 *buf, u16 len)
{
    for (u8 i = 0; i < len; i++) {
        uart_putchar(buf[i]);
    }
}

void uart_putchar_cb(char ch)
{
    uart0_putchar((u8)ch);
}

void iodm_printf_init(void)
{
    my_printf_init(uart_putchar_cb);
}

static u16 calculate_checksum(protocol_frame_t *frame)
{
    u16 sum = 0;
    sum += (frame->frame_head & 0xFF) + (frame->frame_head >> 8);
    sum += (frame->frame_len & 0xFF) + (frame->frame_len >> 8);
    sum += frame->frame_id + frame->cmd_id;
    sum += (frame->cmd_len & 0xFF) + (frame->cmd_len >> 8);

    for (int i = 0; i < frame->cmd_len; i++) {
        sum += frame->cmd_value[i];
    }

    return sum;
}

parse_result_t protocol_frame_parse(uart_datamgr_t *uart_mgr, protocol_frame_t *frame)
{
    int protocol_max_size = 0;
    protocol_max_size = sizeof(protocol_frame_t);
    frame->frame_head = (uart_mgr->buffer[0] << 8) | uart_mgr->buffer[1];

    if (frame->frame_head != FRAME_HEADER) {
        return PARSE_ERROR;
    }

    /* 小端格式传输， 低位在前，高位在后*/
    frame->frame_len = (uart_mgr->buffer[2] << 8) | uart_mgr->buffer[3];
    frame->frame_id = uart_mgr->buffer[4];
    frame->cmd_id = uart_mgr->buffer[5];
    /* 小端格式传输， 低位在前，高位在后 */
    frame->cmd_len = (uart_mgr->buffer[7] << 8) | uart_mgr->buffer[6];
    if (frame->cmd_len > FRAME_CMD_BUFFER_SIZE) {
        return PARSE_ERROR;
    }

    if (frame->cmd_len > 0)
    {
        memcpy(frame->cmd_value, &uart_mgr->buffer[8], frame->cmd_len);
        frame->checksum = (uart_mgr->buffer[8 + frame->cmd_len + 1] << 8) |
                            uart_mgr->buffer[8 + frame->cmd_len];
    }
    else if (frame->cmd_len == 0)
    {
        memset(frame->cmd_value, 0, FRAME_CMD_BUFFER_SIZE);
        frame->checksum = (uart_mgr->buffer[9] << 8) | uart_mgr->buffer[8];
    }
    return PARSE_OK;
} 
  

/* 整理帧数据，部分字段数据以小端传输 */
static void protocol_frame_fmt_parse2buf(protocol_frame_t *frame, u8 *buf)
{
    *buf++ = frame->frame_head >> 8;
    *buf++ = frame->frame_head & 0x00ff;
    *buf++ = frame->frame_len & 0x00ff;
    *buf++ = frame->frame_len >> 8;
    *buf++ = frame->frame_id;
    *buf++ = frame->cmd_id;
    *buf++ = frame->cmd_len & 0x00ff;
    *buf++ = frame->cmd_len >> 8;

    memcpy(buf, frame->cmd_value, frame->cmd_len);
    buf += frame->cmd_len;
    *buf++ = frame->checksum & 0x00ff;
    *buf = frame->checksum >> 8;

}

static int bt_spp_transfer(uint8_t *packet, uint16_t len)
{
    int ret = 0;
    int cnt = 0;

    while (1)
    {
        ret = bt_spp_tx(packet, len);
        my_printf("[ModuleLog]spp_tx_ret: %d\n", ret);
        if (ret != 2)
        {
            delay_ms(10);
            break;
        }

        cnt++;
        if (cnt > SPP_TRANSFER_RETRY_CNT)
        {
            break;
        }
        delay_ms(20);
    }

    return ret;
}

static void protocol_frame_response(u8 cmd_id, u16 cmd_len, u8 *cmd_value)
{
    memset(g_tx_buf, 0x00, sizeof(g_tx_buf));
    protocol_frame_t respone = {0};
    respone.frame_head = FRAME_HEADER;
    respone.frame_len  = cmd_len + 10;
    respone.frame_id   = 0x00;
    respone.cmd_id     = cmd_id;
    respone.cmd_len    = cmd_len;
    if (cmd_value && cmd_len > 0) {
        memcpy(respone.cmd_value, cmd_value, cmd_len);
    }
    respone.checksum   = calculate_checksum(&respone);

    protocol_frame_fmt_parse2buf(&respone, g_tx_buf);
    iodm_uart0_data_send(g_tx_buf, respone.frame_len);
}

static void protocol_frame_process(protocol_frame_t *frame)
{
    int ret = 0;
    char *local_name = NULL;
    char bt_version[32] = {0};
    u8 mac_addr[6] = {0};
    u8 device_status = 0;
    switch (frame->cmd_id) {
        case CMD_ACK_OK:
            /* software reset */
            cm_write8(PARAM_RST_FLAG, RST_FLAG_MAGIC_VALUE);
            cm_sync();
            WDT_RST();
            protocol_frame_response(CMD_ACK_OK, 0, NULL);
            break;

        case CMD_ACK_ERROR:
            break;

        case CMD_SET_BT_RF_ON:
            bt_cfg.scan_ctrl = 1;
            bt_set_scan(true);
            bt_disconnect();
            bt_connect();
            break;

        case CMD_SET_BT_RF_OFF:
            bt_disconnect();
            bt_cfg.scan_ctrl = 1;
            bt_set_scan(false);
            break;

        case CMD_SET_BT_LOCAL_NAME:
            local_name = (char *)frame->cmd_value;
            bt_save_new_name(local_name, frame->cmd_len);
            updata_bt_name(local_name);
            break;

        case CMD_GET_BT_LOCAL_NAME:
            local_name = bt_get_local_name();
            if (local_name) {
                protocol_frame_response(CMD_REPORT_BT_LOCAL_NAME, strlen(local_name) + 1, local_name);
            }
            break;

        case CMD_GET_BT_VERSION:
            memcpy(bt_version, IODM_BT_VERSION, strlen(IODM_BT_VERSION));
            protocol_frame_response(CMD_REPORT_BT_VERSION, strlen(bt_version) + 1, bt_version);
            break;


        case CMD_SET_SPP_TX_DATA:
            my_printf("[ModuleLog]transfer_len : %d\n", frame->cmd_len);
            if (frame->cmd_len > MAX_SPP_TX_DATA_SIZE) {
                u8 packet_num = frame->cmd_len / MAX_SPP_TX_DATA_SIZE;
                u8 remain_len = frame->cmd_len % MAX_SPP_TX_DATA_SIZE;
                for (u8 i = 0; i < packet_num; i++) {
                    ret = bt_spp_transfer(frame->cmd_value + i * MAX_SPP_TX_DATA_SIZE, MAX_SPP_TX_DATA_SIZE);
                    if (ret != 0) {
                        break;
                    }
                }

                if (0 == ret && remain_len > 0) {
                    ret = bt_spp_transfer(frame->cmd_value + packet_num * MAX_SPP_TX_DATA_SIZE, remain_len);
                }
            } else {
                ret = bt_spp_transfer(frame->cmd_value, frame->cmd_len);
            }

            if (ret != 0) {
                protocol_frame_response(CMD_ACK_ERROR, 0, NULL);
                // iodm_log_printf("bt_spp_transfer error,ret : %d", ret);
                return;
            }
            break;

        case CMD_GET_SPP_RX_DATA:
            break;

        case CMD_GET_BT_MAC_ADDR:
            if (bt_get_qr_addr(mac_addr)) {
                protocol_frame_response(CMD_REPORT_BT_MAC_ADDR, sizeof(mac_addr), mac_addr);
            } else {
                if (!bt_get_master_addr(mac_addr)) {
                    memcpy(mac_addr, xcfg_cb.bt_addr, 6);
                }
                protocol_frame_response(CMD_REPORT_BT_MAC_ADDR, sizeof(mac_addr), mac_addr);
            }
            break;

        case CMD_GET_DEVICE_STATUS:
            device_status = bsp_bt_mgr_device_status_get();
            protocol_frame_response(CMD_REPORT_DEVICE_STATUS, 1, &device_status);
            break;

        default:
            break;
    }

    protocol_frame_response(CMD_ACK_OK, 0, NULL);
    return ;
}

// 主循环中的数据处理函数
void iodm_reveice_data_handle(void)
{
#if 1
    parse_result_t result;
    protocol_frame_t *frame = &g_uart_datamgr.frame;

#if 0
    if (g_uart_datamgr.cnt < 512)
    {
        my_printf("\n");
        for (int i = 0; i < g_uart_datamgr.cnt; i++) {
            my_printf("%02x ", g_uart_datamgr.buffer[i]);
        }
        my_printf("\n");
    }
#endif

    // my_printf("[ModuleLog]frame_len: %d\n", g_uart_datamgr.cnt);
    result = protocol_frame_parse(&g_uart_datamgr, frame);

    if (result == PARSE_OK) {
        protocol_frame_process(frame);
    }

    g_uart_datamgr.cnt = 0;
    memset(g_uart_datamgr.buffer, 0, sizeof(g_uart_datamgr.buffer));
    memset(&g_uart_datamgr.frame, 0, sizeof(g_uart_datamgr.frame));

#else
    u16 frame_len = g_uart_datamgr.buffer[2];
    frame_len |= (g_uart_datamgr.buffer[3] << 8);
    if (g_uart_datamgr.buffer[0] == 0xAC && g_uart_datamgr.buffer[1] == 0x69
        && g_uart_datamgr.cnt == frame_len) {
            for (int i = 0; i < g_uart_datamgr.cnt; i++) {
                my_printf("%02x ", g_uart_datamgr.buffer[i]);
            }
            my_printf("\n");
            g_uart_datamgr.cnt = 0;
    } else {
        my_printf("%02x %02x %02x %02x ", g_uart_datamgr.buffer[0], g_uart_datamgr.buffer[1],
                                          g_uart_datamgr.buffer[2], g_uart_datamgr.buffer[3]);
        my_printf("\n");

    }
#endif
}


// 串口中断处理函数
AT(.com_text.uart)
void iodm_test_mode_uart0_isr(void)
{
    if (UART0CON & BIT(9)) {
        UART0CPND = BIT(9);
        u8 data = UART0DATA;

        u16 max_buf_size = sizeof(g_uart_datamgr.buffer);
        if (g_uart_datamgr.cnt >= max_buf_size) {
            g_uart_datamgr.error_type = ERR_BUFFER_OVERFLOW;
            g_uart_datamgr.parse_state = FRAME_FIND_HEAD;
            g_uart_datamgr.cnt = 0;
            memset(g_uart_datamgr.buffer, 0, sizeof(g_uart_datamgr.buffer));
            return;
        }
        /* parse a whole frame and enqueue */
        g_uart_datamgr.buffer[g_uart_datamgr.cnt++] = data;
        if (g_uart_datamgr.buffer[0] != 0xAC) 
        {
            memset(g_uart_datamgr.buffer, 0, sizeof(g_uart_datamgr.buffer));
            g_uart_datamgr.cnt = 0;
            return;
        }
        u16 frame_len = g_uart_datamgr.buffer[2];
        frame_len |= (g_uart_datamgr.buffer[3] << 8);
        if (g_uart_datamgr.buffer[0] == 0xAC && g_uart_datamgr.buffer[1] == 0x69
            && g_uart_datamgr.cnt == frame_len && g_uart_datamgr.cnt >= MIN_FRAME_SIZE)
        {
            msg_enqueue(EVT_IODM_TEST_MODE);
        }
    }
}



static void uart0_init(u32 baudrate)
{
    u32 baud = 0;
    baud = (26000000 / 2 + baudrate / 2) / baudrate - 1; //时钟源x26m_div2 //baud/2 四舍五入
    register_isr(IRQ_UART_VECTOR, iodm_test_mode_uart0_isr);
    UART0CON = 0;
    GPIOBFEN |= (BIT(3) | BIT(4));                       //Port Function EN, use as function io
    GPIOBDIR |= BIT(4);                                  //PB4 input direction
    GPIOBDIR &= ~BIT(3);                                 //PB3 output direction
    GPIOBPU  |= (BIT(3) | BIT(4));                       //TX->PB3 | RX ->PB4, Pull up for these io
    GPIOBDE  |= (BIT(3) | BIT(4));                       //Port as digital IO
    FUNCMCON0 |= (0xf << 8) | (0xf << 12);               //Clear map
    FUNCMCON0 |= (0x3 << 8) | (0x3 << 12);               //TX | RX Map uart0-G3

    UART0BAUD = (baud << 16) | baud;                     //Baudrate = sys_clk/(UART0BAUD + 1)   16~31接收波特率  0~15 发送波特率
    UART0CON |= BIT(7) | BIT(5) | BIT(2) | BIT(0);       //BIT(7)RX使能，BIT(5)使能Uart_inc BIT(3)使能TX中断，BIT(2)使能RX中断，BIT(0)使能串口
    // UART0CON &= ~ (BIT(6) | BIT(5) | BIT(4) | BIT(1));
    CLKCON1 |= BIT(14);
    PICPR &= ~BIT(IRQ_UART_VECTOR);                      //Interrupt priority select
    PICEN |= BIT(IRQ_UART_VECTOR);                       //Interrupt EN
    // uart_0_isr_init(iodm_test_mode_uart0_isr);
}


void iodm_test_mode_uart0_init(void)
{
    memset(&g_uart_datamgr, 0, sizeof(g_uart_datamgr));
    uart0_init(9600);
    // iodm_printf_init();
    printk("iodm_uart0_init %x\n", UART0CON);
    // for (u8 i = 0; i < 5; i++) {
    //     uart0_putchar(0x55);
    // }
}


void iodm_spp_protocol_frame_response(u8 *buf, u16 len)
{
    protocol_frame_response(CMD_REPORT_SPP_RX_DATA, len, buf);
}


int iodm_protocol_frame_response(uint8_t cmd_id, uint16_t cmd_len, uint8_t *cmd_value)
{
    protocol_frame_response(cmd_id, cmd_len, cmd_value);
    return 0;
}


static char *int_to_str(int num, char *str)
{
    char *p = str;
    char tmp[16];
    int i = 0;

    // 处理负数
    if (num < 0) {
        *p++ = '-';
        num = -num;
    }

    // 处理0的特殊情况
    if (num == 0) {
        *p++ = '0';
        *p = '\0';
        return str;
    }

    // 从低位到高位提取数字到临时数组
    while (num > 0) {
        tmp[i++] = (num % 10) + '0';
        num /= 10;
    }

    // 反向拷贝到目标字符串
    while (i > 0) {
        *p++ = tmp[--i];
    }

    *p = '\0';
    return str;
}

static void hex_to_str(unsigned int num, char *str, int uppercase)
{
    const char *hex_chars = uppercase ? "0123456789ABCDEF" : "0123456789abcdef";
    int i = 0;

    // 计算数字的位数
    unsigned int temp = num;
    while (temp) {
        temp >>= 4;
        i++;
    }

    // 如果是0，直接返回
    if (i == 0) {
        *str++ = '0';
        *str = '\0';
        return;
    }

    // 从低位到高位处理数字
    while (num) {
        int rem = num & 0xF;
        *str++ = hex_chars[rem];
        num >>= 4;
    }

    *str = '\0';
}

static void _vsnprintf(char *buf, size_t buf_size, const char *fmt, va_list args)
{
    char *p = buf;
    char temp[16];  // 用于临时存储转换结果
    size_t len = 0;
    int uppercase = 0;  // 用于处理大写/小写

    while (*fmt && len < buf_size - 1) {
        if (*fmt != '%') {
            *p++ = *fmt++;
            len++;
            continue;
        }

        fmt++;
        switch (*fmt) {
            case 's':  // 字符串
            {
                char *str = va_arg(args, char *);
                size_t slen = strlen(str);
                if (len + slen < buf_size - 1) {
                    memcpy(p, str, slen);
                    p += slen;
                    len += slen;
                }
            }
            break;
            case 'd':  // 十进制整数
            {
                int num = va_arg(args, int);
                int_to_str(num, temp);
                size_t tlen = strlen(temp);
                if (len + tlen < buf_size - 1) {
                    memcpy(p, temp, tlen);
                    p += tlen;
                    len += tlen;
                }
            }
            break;
            case 'x':  // 十六进制（小写）
            {
                unsigned int num = va_arg(args, unsigned int);
                hex_to_str(num, temp, 0);  // 0 表示小写
                size_t tlen = strlen(temp);
                if (len + tlen < buf_size - 1) {
                    memcpy(p, temp, tlen);
                    p += tlen;
                    len += tlen;
                }
            }
            break;
            case 'X':  // 十六进制（大写）
            {
                unsigned int num = va_arg(args, unsigned int);
                hex_to_str(num, temp, 1);  // 1 表示大写
                size_t tlen = strlen(temp);
                if (len + tlen < buf_size - 1) {
                    memcpy(p, temp, tlen);
                    p += tlen;
                    len += tlen;
                }
            }
            break;
            case 'c':  // 字符
            {
                int ch = va_arg(args, int);  // 字符在va_arg中作为int传递
                if (len < buf_size - 1) {
                    *p++ = (char)ch;
                    len++;
                }
            }
            break;
            case 'p':  // 指针地址
            {
                void *ptr = va_arg(args, void *);
                unsigned int addr = (unsigned int)ptr;
                hex_to_str(addr, temp, 1);  // 指针地址通常使用大写
                size_t tlen = strlen(temp);
                if (len + tlen < buf_size - 1) {
                    *p++ = '0';
                    *p++ = 'x';
                    memcpy(p, temp, tlen);
                    p += tlen;
                    len += tlen + 2;
                }
            }
            break;
            default:  // 处理未知格式
                if (len < buf_size - 1) {
                    *p++ = '%';
                    len++;
                }
                if (*fmt && len < buf_size - 1) {
                    *p++ = *fmt;
                    len++;
                }
        }
        fmt++;
    }

    *p = '\0';  // 结束字符串
}

void iodm_log_printf(const char *fmt, ...)
{
    va_list args;
    memset(g_log_buf, 0, sizeof(g_log_buf));
    u16 len;

    va_start(args, fmt);
    _vsnprintf(g_log_buf, sizeof(g_log_buf), fmt, args);
    va_end(args);

    len = strlen(g_log_buf);
    if (len <= 0) {
        return;
    }

    protocol_frame_t frame = {0};
    frame.frame_head = FRAME_HEADER;
    frame.frame_len = len + 10;
    frame.frame_id = 0x00;
    frame.cmd_id = CMD_REPORT_BT_LOG;
    frame.cmd_len = len;
    memcpy(frame.cmd_value, g_log_buf, len);
    frame.checksum = calculate_checksum(&frame);

    protocol_frame_fmt_parse2buf(&frame, g_log_buf);
    iodm_uart0_data_send(g_log_buf, frame.frame_len);
}

#endif


AT(.com_text.uart)
void user_uart1_putc(char ch)
{
    while (!(UART1CON & BIT(8)));
    UART1DATA = ch;
}

//打印用PA7
void uart1_debug_init(void)
{

    u32 baud=1500000;//打印固定用
    printf("%s\n",__func__);

    u32 baud_cfg;
//    PA0_RX, PA1_TX example
    GPIOADE  |= BIT(7);
    GPIOADIR &= ~BIT(7);
    GPIOAPU &= ~BIT(7);
    GPIOAFEN |= BIT(7) ;                            //Port Function EN

//    FUNCMCON0 = URX0MAP_TX | UTX0MAP_PA7;           //RX0 Map To TX0, TX0 Map to G1
    FUNCMCON0 |= ((0xFL << 24) | (0xFL << 28));

    UART1CON = 0;          //uart reset

    CLKGAT0|=BIT(21);
    UART1CON |= BIT(5);      //uart_clk sel uart_inc
    CLKCON1 |= BIT(14);      //uart_inc form x26m_div2
//根据config.h主频来改不然会导致波特率不对导致没有打印

//120M
    baud_cfg = (120000000 + baud/2)/baud - 1;  //时钟源x26m_div2 //baud/2 四舍五入         

//26M
//    baud_cfg = (26000000/2 + baud/2)/baud - 1;  //时钟源x26m_div2 //baud/2 四舍五入

    UART1BAUD = (baud_cfg << 16) | baud_cfg; //UARTBAUD = Fsys_clock/BaudRate-1 //16~31 rx_baud  0~15 tx_baud


    UART1CON &=~ (BIT(1)|BIT(4)|BIT(5)|BIT(6));
//    UART1CON &=~ (BIT(1)|BIT(4)|BIT(5)|BIT(6));
    UART1CON |= BIT(0); // BIT(7)RX en，BIT(2)RX INT en，BIT(0)uart en
    UART1CPND = BIT(17) | BIT(16);                              //CLR Pending
    FUNCMCON0 |= (0x1L << 24);       // MAP G5 RX->12~15bit TX->8~11bit

    my_printf_init(user_uart1_putc);

}


